{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = X = np.array([[5, 1], [4, 2], [2, 5], [1,4 ],[3,2],[2,5]])\n",
    "\n",
    "y = np.array([0, 0, 1, 1,0,1]) # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkUAAAHJCAYAAACL5E3/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABhQ0lEQVR4nO3deVxU9f7H8dewo4BriAuiuWHuuKJ1tQzXm9Ji/tBSU+tWWlqpaddyq6yszG5dMzWpbmRZaVaaoYZ75Ua5ZWoqLqhXMxBRHOH8/uAyOTIgAzMMM76fj8c8cr7ne77n85kzkx/P+Z5zTIZhGIiIiIhc57xcHYCIiIhIWaCiSERERAQVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikQ4dOgQJpMJk8lUaL8hQ4ZgMpmYPHly6QTmAHkxm0wm/vGPfxTYLysri8qVK1v6JiUllV6Q/5MXqzO3nZSUZMkx7+Xj40NYWBh9+/bl+++/d9q2r5Sdnc1zzz1HvXr18PPzw2QyMWTIkFLZtogUzMfVAYhI6Vi0aBH/+te/8PPzy7fsm2++4ezZsy6IyjWqVatGjx49ALh48SLJycksXbqUr776irfffptHHnnEqdufNWsW06ZNo0aNGtx1110EBARw8803O3WbInJtKopErgOtWrVi+/btLFu2jNjY2HzL//Of/+Dt7U3Tpk35+eefSz9AYPr06YwfP57atWs7fVuRkZHEx8db3huGwdSpU5k8eTJPPfUUd999N6GhoU7b/pIlSwBYt24dN954o9O2IyL20ekzketAXFwcXl5efPTRR/mW/fnnnyxbtoyuXbsSFhbmguhyVa9encjISMqVK1fq2zaZTDz77LPUq1ePCxcu8N133zl1e0ePHgVQQSRSxqgoEimhjIwMpk+fTosWLahQoQJBQUHUq1ePfv36sWLFinz9MzMzmT59Oq1atSIoKIigoCA6dOjA+++/b3N8k8lEnTp1uHTpElOnTiUyMhJ/f3+bR3wKUr16dW677Ta+/vpr0tLSrJZ9+umnZGVlcd999xU6xpEjR/jHP/5BREQE/v7+hIaGctddd7F582arftu2bcNkMtG+ffsCx/rXv/6FyWTiySeftLQVNqfI3s+sOLy8vGjRogWQmyv8NQdpyJAhnDhxguHDh1OrVi18fHx44403LOseOXKEkSNHUq9ePQICAqhcuTJ///vf2bhxo9U28nI8ePAggNXcpkOHDhU736J8R4o7ZnZ2Ni+//DINGzbE39+f8PBwnn76abKysmyud/78eV5++WXatGlDSEgI5cuXJzIykhEjRvDbb7/l6//jjz/Sr18/qlevjp+fH7Vq1WL48OGkpKTYHF/EmXT6TKQEsrOzuf322/nxxx+pWrUqXbp0ISAggKNHj7Js2TLKly9P9+7dLf1PnTpFTEwMv/zyC2FhYXTu3BnDMNi4cSNDhgxhy5Yt/Otf/8q3nZycHGJjY1m7di2dO3emefPmVKlSxa5YBw4cyMqVK/n8888ZOnSopf2jjz6iXLly3HnnnTaPJAHs2LGD2267jdOnT9OoUSPuuusuUlJSWLx4MV999RUJCQn069cPgKioKCIjI/npp584cOAA9erVyzde3nauVYhB8T+z4jh37hwA/v7+Vu3//e9/adu2LZcvX+bmm2/m4sWLliNamzZtonfv3pw9e5ZGjRrRu3dv/vvf/7JixQq+/fZbPvroI/r37w9gmTf02Wefcf78eQYPHmzZRlBQUInyLew7UpLPcMCAASxbtowuXbrQqFEj1q1bxyuvvMKxY8f4z3/+Y9U3NTWVmJgYdu3aRaVKlejSpQv+/v78/vvvvPPOOzRo0ICGDRta+v/73//mscceA6Bt27bccsst7N27l/nz57N06VLWrFlD48aNi7j3RBzAELnOHTx40ACMa/0cBg8ebADGpEmTLG2rV682AKNt27bGhQsXrPqnpaUZW7ZssWrr1auXARijRo0yLl68aGk/ceKE0aZNGwMwli9fbrVOXmz169c3jh49aldueTF/+OGHRnp6uhEYGGjceuutluWHDx82TCaTERcXZxiGYXTv3t0AjO+//97SJycnx2jWrJkBGOPGjTNycnIsyz777DPDy8vLCAoKMo4fP25pnzZtmgEYU6dOzRfT/v37DcCIjIy0GeuV2zaM4n1mBfn+++8NwOjcuXO+ZSdPnjRCQkIMwEhMTLTqDxh33nmnzX1cvXp1w9vb2/jPf/5jtWzz5s1GpUqVjKCgIOPUqVNWyyIiIgr8vjnjO1KSMRs3bmykpqZa2n///XejYsWKBmDs37/fap2uXbsagHHvvfca586ds1p28OBB4+eff7a837Rpk+Ht7W3U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06cDMGrUKDp37sxrr71G7969WbhwIVu2bOHdd98t9fjz3PjEA9zQ7WYOv7uQszt+5Q8g8oWniLgvFt+KJTs9JyLXcPVl91dOxMw7QvTcc9bvRUQK4PKrzwqTkpJieZgqQMeOHUlISGDixIk888wzNGjQgCVLluQrrkpbcJMGNJ31LGazmWXLlhHxjziPPywq4nJFuQ+RCiMRsUOZKoquftq0radP9+vXj355N2wTketXdnbR7kOUt/yKG6yKiNhSpooiEZEiu8bDXa3oCJGIFIHL72gtIiIiUhaoKBIRERFBRZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBAAfe1d48sknbbabTCYCAgKoX78+ffv2pXLlyiUOTkRERKS02F0Ubd++nW3btpGdnU2jRo0A+O233/D29iYyMpJ///vfPPXUU6xfv56bbrrJ4QGLiIiIOIPdp8/69u3L7bffzvHjx9m6dStbt27l6NGjxMTEEBcXx7Fjx/jb3/7GE088cc2xZs+eTfPmzQkJCSEkJITo6GiWL19eYP/4+HhMJpPVKyAgwN4URERERPKx+0jRjBkzSExMJCQkxNJWoUIFJk+eTLdu3Rg1ahTPPfcc3bp1u+ZYtWrV4qWXXqJBgwYYhsH7779P37592b59O02aNLG5TkhICHv37rW8N5lM9qYgIiIiko/dRVFaWhqnTp3Kd2rsv//9L+np6QBUrFiRS5cuXXOsO+64w+r9Cy+8wOzZs/nhhx8KLIpMJhNhYWH2hi0iIiJSKLuLor59+zJ06FBee+012rZtC8DmzZsZM2YMsbGxAPz00080bNjQrnGzs7NZtGgR58+fJzo6usB+GRkZREREkJOTQ1RUFC+++GKBBRRAVlYWWVlZlvd5hZvZbMZsNtsV47XkjefoccsKT88PPD9H5ef+PD1H5ef+nJVjaXxmJsMwDHtWyMjI4IknnuCDDz7g8uXLAPj4+DB48GBmzpxJ+fLlSU5OBqBly5bXHG/Hjh1ER0dz8eJFgoKCSEhIoFevXjb7btq0iX379tG8eXPS0tJ49dVXWbt2Lbt27aJWrVo215k8eTJTpkzJ156QkEC5cuWKlrSIiIi4VGZmJgMGDCAtLc1qCo8j2V0U5cnIyOD3338H4MYbbyQoKKhYAVy6dImUlBTS0tL47LPPmDdvHmvWrCnSlWtms5nGjRsTFxfHtGnTbPaxdaQoPDyc06dPO/xDNZvNJCYmEhMTg6+vr0PHLgs8PT/w/ByVn/vz9ByVn/tzVo7p6elUrVrVqUWR3afP8gQFBdG8efMSB+Dn50f9+vUBaN26NZs3b2bWrFnMmTPnmuv6+vrSqlUr9u/fX2Aff39//P39ba7rrC+kM8cuCzw9P/D8HJWf+/P0HJWf+3N0jqXxedldFJ0/f56XXnqJVatWcerUKXJycqyW5x09Kq6cnByrIzuFyc7OZseOHQWebhMREREpKruLouHDh7NmzRruv/9+qlevXqJL4idMmEDPnj2pXbs2586dIyEhgaSkJFasWAHAoEGDqFmzJtOnTwdg6tSpdOjQgfr16/Pnn38yY8YMDh8+zPDhw4sdg4iIiAgUoyhavnw533zzDZ06dSrxxk+dOsWgQYNITU2lQoUKNG/enBUrVhATEwNASkoKXl5/3V/y7NmzPPjgg5w4cYJKlSrRunVrNm7cqDtni4iISInZXRRVqlTJYc81mz9/fqHLk5KSrN7PnDmTmTNnOmTbIiIiIley+zEf06ZN47nnniMzM9MZ8YiIiIi4hN1Hil577TUOHDhAtWrVqFOnTr7Z4Nu2bXNYcCIiIiKlxe6iKO+u1SIiIiKexO6iaNKkSc6IQ0RERMSl7J5TJCIiIuKJinSkqHLlyvz2229UrVqVSpUqFXpvoj/++MNhwYmIiIiUliIVRTNnziQ4ONjy55LcsFFERESkLCpSUTR48GDLn4cMGeKsWERERERcxu45Rd7e3pw6dSpf+5kzZ/D29nZIUCIiIiKlze6iyDAMm+1ZWVn4+fmVOCARERERVyjyJflvvvkmACaTiXnz5hEUFGRZlp2dzdq1a4mMjHR8hCIiIiKloMhFUd4zxwzD4J133rE6Vebn50edOnV45513HB+hiIiISCkoclF08OBBAG699Va++OILKlWq5LSgREREREqb3Xe0/v77750Rh4iIiIhL2V0UARw9epSlS5eSkpLCpUuXrJa9/vrrDglMREREpDTZXRStWrWKPn36cOONN/Lrr7/StGlTDh06hGEYREVFOSNGEREREaez+5L8CRMmMGbMGHbs2EFAQACff/45R44coXPnzvTr188ZMYqIiIg4nd1F0Z49exg0aBAAPj4+XLhwgaCgIKZOncrLL7/s8ABFRERESoPdRVH58uUt84iqV6/OgQMHLMtOnz7tuMhERERESpHdc4o6dOjA+vXrady4Mb169eKpp55ix44dfPHFF3To0MEZMYqIiIg4nd1F0euvv05GRgYAU6ZMISMjg08++YQGDRroyjMRERFxW3YVRdnZ2Rw9epTmzZsDuafSdBdrERER8QR2zSny9vamW7dunD171lnxiIiIiLiE3ROtmzZtyu+//+6MWERERERcxu6i6Pnnn2fMmDF8/fXXpKamkp6ebvUSERERcUd2T7Tu1asXAH369MFkMlnaDcPAZDKRnZ3tuOhERERESokeCCsiIiJCMYqizp07OyMOEREREZeye06RiIiIiCdSUSQiIiKCiiIRERERwMVF0ezZs2nevDkhISGEhIQQHR3N8uXLC11n0aJFREZGEhAQQLNmzVi2bFkpRSsiIiKerMRF0aVLlyzPQrNXrVq1eOmll9i6dStbtmzhtttuo2/fvuzatctm/40bNxIXF8ewYcPYvn07sbGxxMbGsnPnzpKkICIiImJfUbRgwQIee+wxPvroIwAmTJhAcHAwFSpUICYmhjNnzti18TvuuINevXrRoEEDGjZsyAsvvEBQUBA//PCDzf6zZs2iR48ejB07lsaNGzNt2jSioqJ466237NquiIiIyNWKfEn+Cy+8wAsvvECnTp1ISEhg/fr1LFmyhKlTp+Ll5cWbb77JxIkTmT17drECyc7OZtGiRZw/f57o6GibfTZt2sSTTz5p1da9e3eWLFlS4LhZWVlkZWVZ3ufdddtsNmM2m4sVa0HyxnP0uGWFp+cHnp+j8nN/np6j8nN/zsqxND4zk2EYRlE6NmjQgKlTpxIXF8eWLVto3749n376KXfffTcAy5cv5+GHH+bw4cN2BbBjxw6io6O5ePEiQUFBJCQkWO6afTU/Pz/ef/994uLiLG3//ve/mTJlCidPnrS5zuTJk5kyZUq+9oSEBMqVK2dXrCIiIuIamZmZDBgwgLS0NEJCQpyyjSIfKUpJSeHmm28GoE2bNvj4+NC0aVPL8ubNm5Oammp3AI0aNSI5OZm0tDQ+++wzBg8ezJo1a7jpppvsHsuWCRMmWB1dSk9PJzw8nG7dujn8QzWbzSQmJhITE4Ovr69Dxy4LPD0/8PwclZ/78/QclZ/7c1aOpfF81SIXRWazGX9/f8t7Pz8/q2R9fHyK9dwzPz8/6tevD0Dr1q3ZvHkzs2bNYs6cOfn6hoWF5TsidPLkScLCwgoc39/f3yruPL6+vk77Qjpz7LLA0/MDz89R+bk/T89R+bk/R+dYGp+XXY/52L17NydOnAByHwD766+/Wq48O336tEMCysnJsZoDdKXo6GhWrVrF6NGjLW2JiYkFzkESERERKSq7iqKuXbty5RSkv//97wCYTCYMw8BkMtm18QkTJtCzZ09q167NuXPnSEhIICkpiRUrVgAwaNAgatasyfTp0wEYNWoUnTt35rXXXqN3794sXLiQLVu28O6779q1XREREZGrFbkoOnjwoMM3furUKQYNGkRqaioVKlSgefPmrFixgpiYGCB3HpOX1193DejYsSMJCQlMnDiRZ555hgYNGrBkyRKruU0iIiIixVHkoigiIsLhG58/f36hy5OSkvK19evXj379+jk8FhEREbm+6dlnIiIiIqgoEhEREQFUFImIiIgAKopEREREgGIWRZcvX2blypXMmTOHc+fOAXD8+HHLPYtERERE3I1d9ykCOHz4MD169CAlJYWsrCxiYmIIDg7m5ZdfJisri3feeccZcYqIiIg4ld1HikaNGkWbNm04e/YsgYGBlvY777yTVatWOTQ4ERERkdJi95GidevWsXHjRvz8/Kza69Spw7FjxxwWmIiIiEhpsvtIUU5Ojs0Hvx49epTg4GCHBCUiIiJS2uwuirp168Ybb7xheW8ymcjIyGDSpEn06tXLkbGJiIiIlBq7T5+99tprdO/enZtuuomLFy8yYMAA9u3bR9WqVfn444+dEaOIiIiI09ldFNWqVYuff/6ZhQsX8ssvv5CRkcGwYcMYOHCg1cRrEREREXdid1EE4OPjw3333efoWERERERcpkhF0dKlS+nZsye+vr4sXbq00L59+vRxSGAiIiIipalIRVFsbCwnTpwgNDSU2NjYAvuZTCabV6aJiIiIlHVFKopycnJs/llERETEU9h9Sf6RI0ecEYeIiIiIS9ldFNWpU4fOnTszd+5czp4964yYREREREqd3UXRli1baNeuHVOnTqV69erExsby2WefkZWV5Yz4REREREqF3UVRq1atmDFjBikpKSxfvpwbbriBhx56iGrVqjF06FBnxCgiIiLidHYXRXlMJhO33norc+fOZeXKldStW5f333/fkbGJiIiIlJpiF0VHjx7llVdeoWXLlrRr146goCDefvttR8YmIiIiUmrsvqP1nDlzSEhIYMOGDURGRjJw4EC+/PJLIiIinBGfiIiISKmwuyh6/vnniYuL480336RFixbOiElERESk1NldFKWkpGAymZwRi4iIiIjL2F0UmUwm/vzzT+bPn8+ePXsAuOmmmxg2bBgVKlRweIAiIiIipaFY9ymqV68eM2fO5I8//uCPP/5g5syZ1KtXj23btjkjRhERERGns/tI0RNPPEGfPn2YO3cuPj65q1++fJnhw4czevRo1q5d6/AgRURERJzN7qJoy5YtVgURgI+PD+PGjaNNmzYODU5ERESktNh9+iwkJISUlJR87UeOHCE4ONghQYmIiIiUNruLov79+zNs2DA++eQTjhw5wpEjR1i4cCHDhw8nLi7OGTGKiIiIOJ3dRdGrr77KXXfdxaBBg6hTpw516tRhyJAh3HPPPbz88st2jTV9+nTatm1LcHAwoaGhxMbGsnfv3kLXiY+Px2QyWb0CAgLsTUNERETEit1zivz8/Jg1axbTp0/nwIEDANSrV49y5crZvfE1a9YwYsQI2rZty+XLl3nmmWfo1q0bu3fvpnz58gWuFxISYlU86b5JIiIiUlJ2F0V5ypUrR7NmzUq08W+//dbqfXx8PKGhoWzdupW//e1vBa5nMpkICwsr0bZFRERErlTkomjo0KFF6vfee+8VO5i0tDQAKleuXGi/jIwMIiIiyMnJISoqihdffJEmTZrY7JuVlUVWVpblfXp6OgBmsxmz2VzsWG3JG8/R45YVnp4feH6Oys/9eXqOys/9OSvH0vjMTIZhGEXp6OXlRUREBK1ataKwVRYvXlysQHJycujTpw9//vkn69evL7Dfpk2b2LdvH82bNyctLY1XX32VtWvXsmvXLmrVqpWv/+TJk5kyZUq+9oSEhGKd8hMREZHSl5mZyYABA0hLSyMkJMQp2yhyUTRixAg+/vhjIiIieOCBB7jvvvuueUTHHo888gjLly9n/fr1NoubgpjNZho3bkxcXBzTpk3Lt9zWkaLw8HBOnz7t8A/VbDaTmJhITEwMvr6+Dh27LPD0/MDzc1R+7s/Tc1R+7s9ZOaanp1O1alWnFkVFPn329ttv8/rrr/PFF1/w3nvvMWHCBHr37s2wYcPo1q1biSY7jxw5kq+//pq1a9faVRAB+Pr60qpVK/bv329zub+/P/7+/jbXc9YX0pljlwWenh94fo7Kz/15eo7Kz/05OsfS+LzsuiTf39+fuLg4EhMT2b17N02aNOHRRx+lTp06ZGRk2L1xwzAYOXIkixcvZvXq1dStW9fuMbKzs9mxYwfVq1e3e10RERGRPMW++szLywuTyYRhGGRnZxdrjBEjRpCQkMCXX35JcHAwJ06cAKBChQoEBgYCMGjQIGrWrMn06dMBmDp1Kh06dKB+/fr8+eefzJgxg8OHDzN8+PDipiIiIiJi35GirKwsPv74Y2JiYmjYsCE7duzgrbfeIiUlhaCgILs3Pnv2bNLS0ujSpQvVq1e3vD755BNLn5SUFFJTUy3vz549y4MPPkjjxo3p1asX6enpbNy4kZtuusnu7YuIiIjkKfKRokcffZSFCxcSHh7O0KFD+fjjj6latWqJNl6UOd5JSUlW72fOnMnMmTNLtF0RERGRqxW5KHrnnXeoXbs2N954I2vWrGHNmjU2+33xxRcOC05ERESktBS5KBo0aJAepyEiIiIeq8hFUXx8vBPDEBEREXEtuyZai4iIiHgqFUUiIiIiqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIuKhzpw5Q2hoKIcOHSrV7V66dIk6deqwZcuWUt2uJ9I+lNKmokhEPNILL7xA3759qVOnDpD7F2yPHj2oUaMG/v7+hIeHM3LkSNLT0+0ad/r06bRt25bg4GBCQ0OJjY1l7969luV+fn6MGTOGp59+2pHpXJeu3odXOnPmDLVq1cJkMvHnn3/aNa72oRRERZGIeJzMzEzmz5/PsGHDLG1eXl707duXpUuX8ttvvxEfH8/KlSt5+OGH7Rp7zZo1jBgxgh9++IHExETMZjPdunXj/Pnzlj4DBw5k/fr17Nq1y2E5XW9s7cMrDRs2jObNmxdrbO1DKYiKIhHxOMuXL8ff358OHTpY2ipVqsQjjzxCmzZtiIiIoGvXrjz66KOsW7fOrrG//fZbhgwZQpMmTWjRogXx8fGkpKSwdetWq2116tSJhQsXOiyn642tfZhn9uzZ/Pnnn4wZM6ZYY2sfSkF8XB2AiIijbdiwgdatWxfa5/jx43zxxRd07ty5RNtKS0sDoHLlylbt7dq1s7vgkr8UtA93797N1KlT+fHHH/n9998dsi3tQ8mjI0Ui4nEOHz5MjRo1bC6Li4ujXLly1KxZk5CQEObNm1fs7eTk5DB69Gg6depE06ZNrZbVqFGDw4cPF3vs652tfZiVlUVcXBwzZsygdu3aDtmO9qFcSUWRiHicixcvEhAQYHPZzJkz2bZtG19++SUHDhzgySefLPZ2RowYwc6dO22eYgkMDCQzM7PYY1/vbO3DCRMm0LhxY+677z6HbUf7UK6kokhEPE6VKlU4e/aszWVhYWFERkbSp08f5syZw+zZs0lNTbV7GyNHjuTrr7/m+++/p1atWvmW//HHH9xwww12jyu5bO3D1atXs2jRInx8fPDx8aFr164AVK1alUmTJtm9De1DuZrmFImIx2nZsiUff/zxNfvl5OQAuadlisowDB577DEWL15MUlISdevWtdlv586dtGrVqsjjijVb+/Dzzz/nwoULlvebN29m6NChrFu3jnr16hV5bO1DKYiOFImIx4mJiWHXrl1WRxqWLVvGggUL2LlzJ4cOHeKbb77h4YcfplOnTjbvg1OQESNG8J///IeEhASCg4M5ceIEJ06csPrLGmDdunV069bNUSldd2ztw3r16tG0aVPLK6+Yady4MaGhoUUeW/tQCqKiSEQ8TrNmzYiKiuLTTz+1tAUGBjJ37lxuvvlmGjduzBNPPEGfPn34+uuvLX0OHTqEyWQiKSmpwLFnz55NWloaXbp0oXr16pbXJ598YumzadMm0tLSuOeee5yS3/XA1j4sCu1DKQmdPhMRj/Tcc88xduxYHnzwQby8vLj11lvZuHFjoescPHiQihUr0qJFiwL7GIZxzW2/8cYbjB07lsDAQLvjlr9cvQ+v1qVLl3z7Q/tQSkJFkYh4pN69e7Nv3z6OHTtGeHh4kdZZtmwZzzzzDJUqVSr2di9dukSzZs144oknij2G5NI+lNKmokhEPNbo0aPt6j9jxowSb9PPz4+JEyeWeBzJpX0opUlzikTE7Z04dZG35h9gwMM/ATBq4s+s+P4k2dnXPk0iZcOOPWk8+9Ju7hn2AwDTXv+Vn3eluTgqud64tCi61pOKC7Jo0SIiIyMJCAigWbNmLFu2rBSiFZGyaPdv6dw/YgufLj3KmbNmAH7bn8G013/lny/u4vLlHBdHKNfy2VfHeGRcMms3/ZdzGdkAbNp8hhHjk/l06VEXRyfXE5cWRUV5UvHVNm7cSFxcHMOGDWP79u3ExsYSGxvLzp07SzFyESkLzOYcxk/bSdalbHKuqH1y/neAaMPmMyxcor9Uy7LfDpzjjXf3A5B9xT7M+/Obcw/w6/5zLohMrkcuLYqK8qTiq82aNYsePXowduxYGjduzLRp04iKiuKtt94qxchFpCxY+8Np/vjTbFUQXckwYNHSYzqNVoZ9/vUxvL1NBS739oYvvj5WihHJ9axMTbQu6EnFV9q0aVO+ZxV1796dJUuW2OyflZVldbfa9PR0AMxmM2azuYQRW8sbz9HjlhWenh94fo6elt/uvWcJDMBS9Pj5Wv8X4FxGFidOnSe0qr9LYnQ0T9uHu/b+ibdXDt7/+ye6rX24c+9Zj8nX0/afLc7KsTQ+M5NRlBs2lIKcnBz69OnDn3/+yfr16wvs5+fnx/vvv09cXJyl7d///jdTpkzh5MmT+fpPnjyZKVOm5GtPSEigXLlyjgleREREnCozM5MBAwaQlpZGSEiIU7ZRZo4U5T2puLCCqDgmTJhgdWQpPT2d8PBwunXr5vAP1Ww2k5iYSExMDL6+vg4duyzw9PzA83P0tPy2/HyWf7642/Lez9fgkQHpzE4I4ZLZhMkENasHMO/1KEymgk/RuBNP24dzPjzIkmXHLadAr96HXl7Qt0d1Hh58o2sDdRBP23+2OCvHvDM9zlQmiqK8JxWvXbvW5pOKrxQWFpbviNDJkycJCwuz2d/f3x9///yHzX19fZ32hXTm2GWBp+cHnp+jp+TXPuoGqoeV5+ixTKtJupfMJi6Zc4ug/rF18PPzc1GEzuMp+/DOXuF8/tUJLmcbXHneIm8f+viYuLNXbY/I9Uqesv8K4+gcS+PzculEa8MwGDlyJIsXL2b16tUFPqn4StHR0axatcqqLTExkejoaGeFKSJllJeXiRnPNeWG/80XyjsY5O2d+98Bd9WiV9dqLopOiqJmWCDPT2iCj0/uUaE8Xl7g62Pi+fE3UauGHrUhpcOlR4pGjBhBQkICX375peVJxQAVKlSwPG9m0KBB1KxZk+nTpwMwatQoOnfuzGuvvUbv3r1ZuHAhW7Zs4d1333VZHiLiOjXCAvnw7basXHOKNRtPAmnEdA7ljm61aNzQOfMOxLE6tavCp3Pbs/TbVJJ3nQHSiIutxR09wj1mgry4B5cWRbNnzwZyH+p3pQULFjBkyBAAUlJSrB4E2LFjRxISEpg4cSLPPPMMDRo0YMmSJTRt2rS0whaRMiYwwJs7ulenx21VWbbsME/8o4HHn5rwNDdU8WfYwDqYzTVZtuwog/pHaB9KqXNpUVSUC9+SkpLytfXr149+/fo5ISIRERG5XunZZyIiIiKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICODiomjt2rXccccd1KhRA5PJxJIlSwrtn5SUhMlkyvc6ceJE6QQsIiIiHsulRdH58+dp0aIFb7/9tl3r7d27l9TUVMsrNDTUSRGKiIjI9cLHlRvv2bMnPXv2tHu90NBQKlas6PiARERE5Lrl0qKouFq2bElWVhZNmzZl8uTJdOrUqcC+WVlZZGVlWd6np6cDYDabMZvNDo0rbzxHj1tWeHp+4Pk5Kj/35+k5Kj/356wcS+MzMxmGYTh9K0VgMplYvHgxsbGxBfbZu3cvSUlJtGnThqysLObNm8eHH37Ijz/+SFRUlM11Jk+ezJQpU/K1JyQkUK5cOUeFLyIiIk6UmZnJgAEDSEtLIyQkxCnbcKuiyJbOnTtTu3ZtPvzwQ5vLbR0pCg8P5/Tp0w7/UM1mM4mJicTExODr6+vQscsCT88PPD9H5ef+PD1H5ef+nJVjeno6VatWdWpR5Janz67Url071q9fX+Byf39//P3987X7+vo67QvpzLHLAk/PDzw/R+Xn/jw9R+Xn/hydY2l8Xm5/n6Lk5GSqV6/u6jBERETEzbn0SFFGRgb79++3vD948CDJyclUrlyZ2rVrM2HCBI4dO8YHH3wAwBtvvEHdunVp0qQJFy9eZN68eaxevZrvvvvOVSmIiIiIh3BpUbRlyxZuvfVWy/snn3wSgMGDBxMfH09qaiopKSmW5ZcuXeKpp57i2LFjlCtXjubNm7Ny5UqrMURERESKw6VFUZcuXShsnnd8fLzV+3HjxjFu3DgnRyUiIiLXI7efUyQiIiLiCCqKRERERFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiDjJmTNnCA0N5dChQ6W+7Q4dOvD555/btY6KIhEREXGKF154gb59+1KnTh1Lm8lkyvdauHChXeOuXbuWO+64gxo1amAymViyZEm+PhMnTmT8+PHk5OQUeVwVRSIiIuJwmZmZzJ8/n2HDhuVbtmDBAlJTUy2v2NhYu8Y+f/48LVq04O233y6wT8+ePTl37hzLly8v8rg+dkUhIiIiUgTLly/H39+fDh065FtWsWJFwsLCij12z5496dmzZ6F9vL296dWrFwsXLqR3795FGldHikRERMThNmzYQOvWrW0uGzFiBFWrVqVdu3a89957GIbhlBjatWvHunXritxfR4pERETE4Q4fPkyNGjXytU+dOpXbbruNcuXK8d133/Hoo4+SkZHB448/7vAYatSowZEjR8jJycHL69rHgVQUiYiIiMNdvHiRgICAfO3PPvus5c+tWrXi/PnzzJgxwylFUWBgIDk5OWRlZREYGHjN/jp9JiIiIg5XpUoVzp49e81+7du35+jRo2RlZTk8hj/++IPy5csXqSACFUUiIiLiBC1btmT37t3X7JecnEylSpXw9/d3eAw7d+6kVatWRe6v02ciIiLicDExMUycOJGzZ89SqVIlAL766itOnjxJhw4dCAgIIDExkRdffJExY8bYNXZGRgb79++3vD948CDJyclUrlyZ2rVrW9rXrVtHt27dijyujhSJiIiIwzVr1oyoqCg+/fRTS5uvry9vv/020dHRtGzZkjlz5vD6668zadIkS59Dhw5hMplISkoqcOwtW7bQqlUry1GgJ598klatWvHcc89Z+hw7doyNGzfywAMP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P9HR0YWeviuIr6+v1XuTyVSiydwi4lw6UiQiNuXN48mb53O1evXq4efnx4YNGyxtZrOZzZs3c9NNN1naBgwYwM6dO9m6dSufffYZAwcOLHCbUVFR7Nu3j9DQUOrXr2/1qlChgs11PvroI2rVqsXPP/9McnKy5fXaa68RHx9Pdna2XXlv2LCBxx9/nF69etGkSRP8/f05ffq0VR9fX1+7x71ao0aNuHz5Mtu3b7e07d+/n7Nnz5ZoXBEpPhVFImKTt7c3e/bsYffu3VangPKUL1+eRx55hLFjx/Ltt9+ye/duHnzwQTIzMxk2bJilX506dejYsSPDhg0jOzubPn36FLjNgQMHUrVqVfr27cu6des4ePAgSUlJPP744xw9etTmOvPnz+eee+6hadOmVq9hw4Zx+vRpvv32W7vybtCgAR9++CF79uzhxx9/ZODAgQQGBlr1qVOnDqtWreLEiRPFLmIiIyO5/fbbeeihh/jpp5/Yvn07Dz30kM2jVyJSOlQUiUiBQkJCCAkJKXD5Sy+9xN133839999PVFQU+/fvZ8WKFfnmxQwcOJCff/6ZO++8M1+BcaVy5cqxdu1aateuzV133UXjxo0ZNmwYFy9etBnH1q1b+fnnn7n77rvzLatQoQJdu3Zl/vz5dmScW2SdPXuWqKgo7r//fsstB6702muvkZiYSHh4eL7bFNjjgw8+oFq1avztb3/jzjvv5MEHHyQ4OJiAgIBijykixWcyDMNwdRAiIgJHjx4lPDyclStX0rVrV1eHI3LdUVEkIuIiq1evJiMjg2bNmpGamsq4ceM4duwYv/32W75J2iLifLr6TETERcxmM8888wy///47wcHBdOzYkY8++kgFkYiL6EiRiIiICJpoLSIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICwP8DpcxSxOtPrtwAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm, label=['Action', 'Comedy'])\n",
    "\n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "plt.plot(new_user[0, 0], new_user[0, 1], 'rx', markersize=8)\n",
    "\n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)\n",
    "nearest_idx = idx[0][0]\n",
    "nearest = X[nearest_idx] # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "plt.plot([new_user[0, 0], nearest[0]], [new_user[0, 1], nearest[1]], 'r--')\n",
    "\n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):\n",
    "    plt.text(x, y+0.1, f'({x}, {y})') \n",
    "\n",
    "# 为新数据点添加坐标文本\n",
    "plt.text(new_user[0,0], new_user[0,1]+0.1, f'({new_user[0,0]}, {new_user[0,1]})')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
